Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add image control to download and print map #202

Open
wants to merge 9 commits into
base: 2.x
Choose a base branch
from

Conversation

paul121
Copy link
Member

@paul121 paul121 commented Jul 12, 2024

Adds an image control (naming?) that allows the user to download an image of the current map view or, using printjs, opens a print dialog with the map.

I implemented this as a OL Control and wrapped it with a behavior (similar to snapping grid). It won't be added to maps by default unless the behavior is explicitly added.

@paul121
Copy link
Member Author

paul121 commented Jul 12, 2024

First, click the "Capture image" button. Then the "Download" and "Print" buttons will appear. The download is a link like: <a href={data url} download/> and the print button will open print dialog. If the map is clicked, moved or changed then the "Download" and "Print" buttons are hidden again, and the "Capture image" button must be clicked again.

Screenshot from 2024-07-12 13-35-07

Copy link
Collaborator

@symbioquine symbioquine left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start! Thanks for working on this @paul121

examples/simple-html-consumer/static/index.html Outdated Show resolved Hide resolved
// Create the image button element.
const className = options.className || 'ol-image';
const button = document.createElement('button');
button.innerHTML = options.label || '<svg id="Layer_1" style="enable-background:new 0 0 30 30;" version="1.1" viewBox="0 0 30 30" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M6,19V17c0-0.552-0.448-1-1-1H5c-0.552,0-1,0.448-1,1V19c0,0.552,0.448,1,1,1H5C5.552,20,6,19.552,6,19z"/><path d="M10,5L10,5c0,0.553,0.448,1,1,1H13c0.552,0,1-0.448,1-1V5c0-0.552-0.448-1-1-1H11C10.448,4,10,4.448,10,5z"/><path d="M5,14L5,14c0.553,0,1-0.448,1-1V11c0-0.552-0.448-1-1-1H5c-0.552,0-1,0.448-1,1V13C4,13.552,4.448,14,5,14z"/><path d="M23,6h1l0,1c0,0.552,0.448,1,1,1h0c0.552,0,1-0.448,1-1V6c0-1.105-0.895-2-2-2h-1c-0.552,0-1,0.448-1,1v0 C22,5.552,22.448,6,23,6z"/><path d="M16,5L16,5c0,0.552,0.448,1,1,1h2c0.552,0,1-0.448,1-1v0c0-0.552-0.448-1-1-1h-2C16.448,4,16,4.448,16,5z"/><path d="M7,24H6v-1c0-0.552-0.448-1-1-1H5c-0.552,0-1,0.448-1,1v1c0,1.105,0.895,2,2,2h1c0.552,0,1-0.448,1-1V25 C8,24.448,7.552,24,7,24z"/><path d="M6,7V6h1c0.552,0,1-0.448,1-1V5c0-0.552-0.448-1-1-1H6C4.895,4,4,4.895,4,6v1c0,0.552,0.448,1,1,1H5C5.552,8,6,7.552,6,7z"/><path d="M24,11l0,2.001c0,0.552,0.448,1,1,1h0c0.552,0,1-0.448,1-1V11c0-0.552-0.448-1-1-1h0C24.448,10,24,10.448,24,11z"/></g><g><path d="M25,16h-1.764c-0.758,0-1.45-0.428-1.789-1.106l-0.171-0.342C21.107,14.214,20.761,14,20.382,14h-4.764 c-0.379,0-0.725,0.214-0.894,0.553l-0.171,0.342C14.214,15.572,13.521,16,12.764,16H11c-0.552,0-1,0.448-1,1v8c0,0.552,0.448,1,1,1 h14c0.552,0,1-0.448,1-1v-8C26,16.448,25.552,16,25,16z M18,25c-2.209,0-4-1.791-4-4c0-2.209,1.791-4,4-4s4,1.791,4,4 C22,23.209,20.209,25,18,25z"/><circle cx="18" cy="21" r="2"/></g></svg>';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try applying my minification/standardization process to this SVG? #179 (comment)


// Create a print button.
const print = document.createElement('button');
print.innerHTML = '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><title/><g><path d="M359,184H147a15,15,0,0,1-15-15V63a15,15,0,0,1,15-15H359a15,15,0,0,1,15,15V169A15,15,0,0,1,359,184ZM162,154H344V78H162Z"/><path d="M359,450H147a15,15,0,0,1-15-15V272.09a15,15,0,0,1,15-15H359a15,15,0,0,1,15,15V435A15,15,0,0,1,359,450ZM162,420H344V287.09H162Z"/><path d="M407.25,379H359a15,15,0,0,1,0-30h48.25a18.9,18.9,0,0,0,18.88-18.88V202.89A18.9,18.9,0,0,0,407.25,184H98.75a18.9,18.9,0,0,0-18.88,18.89V330.12A18.9,18.9,0,0,0,98.75,349H147a15,15,0,0,1,0,30H98.75a48.94,48.94,0,0,1-48.88-48.88V202.89A48.94,48.94,0,0,1,98.75,154h308.5a48.94,48.94,0,0,1,48.88,48.89V330.12A48.94,48.94,0,0,1,407.25,379Z"/><path d="M131,236a14.66,14.66,0,0,1-1.48-.07c-.48-.05-1-.13-1.45-.22s-1-.22-1.43-.36-.93-.31-1.38-.5-.89-.4-1.32-.63a12.45,12.45,0,0,1-1.27-.75c-.4-.27-.8-.56-1.18-.87s-.75-.65-1.1-1-.68-.72-1-1.1a14.34,14.34,0,0,1-.87-1.18q-.41-.62-.75-1.26c-.23-.43-.44-.88-.63-1.33s-.35-.92-.5-1.38-.26-1-.36-1.43-.17-1-.22-1.45a15.68,15.68,0,0,1,0-3c.05-.48.13-1,.22-1.45s.22-1,.36-1.43.31-.93.5-1.38.4-.9.63-1.33.48-.85.75-1.26a14.34,14.34,0,0,1,.87-1.18c.31-.38.65-.75,1-1.1s.72-.68,1.1-1,.78-.6,1.18-.87a12.45,12.45,0,0,1,1.27-.75q.65-.34,1.32-.63c.45-.19.92-.35,1.38-.5s1-.26,1.43-.36,1-.17,1.45-.22a16.15,16.15,0,0,1,2.95,0c.49.05,1,.13,1.46.22s1,.22,1.42.36.94.31,1.39.5.89.4,1.32.63a13.63,13.63,0,0,1,1.27.75c.4.27.8.56,1.18.87s.75.65,1.1,1,.67.72,1,1.1.6.78.87,1.18.52.83.75,1.26.44.88.63,1.33.35.92.5,1.38.26,1,.36,1.43.17,1,.22,1.45a15.68,15.68,0,0,1,0,3c-.05.48-.13,1-.22,1.45s-.22,1-.36,1.43-.31.93-.5,1.38-.4.9-.63,1.33-.48.85-.75,1.26-.57.8-.87,1.18-.65.75-1,1.1-.72.68-1.1,1-.78.6-1.18.87a13.63,13.63,0,0,1-1.27.75q-.65.34-1.32.63c-.45.19-.92.35-1.39.5s-.94.26-1.42.36-1,.17-1.46.22A14.46,14.46,0,0,1,131,236Z"/><path d="M175,236c-.49,0-1,0-1.48-.07s-1-.13-1.45-.22-1-.22-1.43-.36-.93-.31-1.38-.5-.9-.4-1.33-.63-.85-.48-1.26-.75a14.34,14.34,0,0,1-1.18-.87c-.38-.31-.75-.65-1.1-1s-.68-.72-1-1.1-.6-.78-.87-1.18a14.69,14.69,0,0,1-.76-1.27c-.22-.43-.43-.87-.62-1.32s-.35-.92-.5-1.38-.26-1-.36-1.43-.17-1-.22-1.45a15.68,15.68,0,0,1,0-3c.05-.48.13-1,.22-1.45s.22-1,.36-1.43.31-.93.5-1.38.4-.89.62-1.32a14.69,14.69,0,0,1,.76-1.27c.27-.4.56-.8.87-1.18s.65-.75,1-1.1.72-.68,1.1-1a14.34,14.34,0,0,1,1.18-.87q.62-.41,1.26-.75c.43-.23.88-.44,1.33-.63s.92-.35,1.38-.5,1-.26,1.43-.36,1-.17,1.45-.22a16.26,16.26,0,0,1,3,0c.48.05,1,.13,1.45.22s1,.22,1.43.36.93.31,1.38.5.89.4,1.32.63.86.48,1.27.75.8.56,1.18.87.75.65,1.1,1,.67.72,1,1.1.6.78.87,1.18a14.6,14.6,0,0,1,.75,1.27q.34.65.63,1.32c.19.45.35.92.5,1.38s.26,1,.36,1.43.17,1,.22,1.45a15.68,15.68,0,0,1,0,3c-.05.48-.13,1-.22,1.45s-.22,1-.36,1.43-.31.93-.5,1.38-.4.89-.63,1.32a14.6,14.6,0,0,1-.75,1.27c-.27.4-.57.8-.87,1.18s-.65.75-1,1.1-.72.68-1.1,1-.78.6-1.18.87-.84.52-1.27.75-.87.44-1.32.63-.92.35-1.38.5-1,.26-1.43.36-1,.17-1.45.22S175.49,236,175,236Z"/><path d="M312,344H194a15,15,0,0,1,0-30H312a15,15,0,0,1,0,30Z"/><path d="M312,397H194a15,15,0,0,1,0-30H312a15,15,0,0,1,0,30Z"/></g></svg>';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for this one.

src/control/Image/Image.js Outdated Show resolved Hide resolved
src/control/Image/Image.js Outdated Show resolved Hide resolved
src/control/Image/Image.js Outdated Show resolved Hide resolved
src/control/Image/Image.js Outdated Show resolved Hide resolved
src/control/Image/Image.js Outdated Show resolved Hide resolved
src/control/Image/Image.js Outdated Show resolved Hide resolved
Copy link
Member

@mstenta mstenta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be a great option! Thanks for working on it @paul121!

Great feedback @symbioquine. I don't have anything to add at this point.

Comment on lines +87 to +110
// Draw each canvas from this map into the new canvas.
// Logic for transforming and drawing canvases derived from ol export-pdf example.
// https://github.com/openlayers/openlayers/blob/6f2ca3b9635f273f6fbddab834bd9126c7d48964/examples/export-pdf.js#L61-L85
Array.from(this.getMap().getTargetElement().querySelectorAll('.ol-layer canvas'))
.filter(canvas => canvas.width > 0)
.forEach((canvas) => {
const { opacity } = canvas.parentNode.style;
outputContext.globalAlpha = opacity === '' ? 1 : Number(opacity);

// Get the transform parameters from the style's transform matrix.
// This is necessary so that vectors align with raster layers.
const { transform } = canvas.style;
const matrix = transform
.match(/^matrix\(([^(]*)\)$/)[1]
.split(',')
.map(Number);

// Apply the transform to the export map context.
CanvasRenderingContext2D.prototype.setTransform.apply(
outputContext,
matrix,
);
outputContext.drawImage(canvas, 0, 0);
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about this @symbioquine ? Implementing the transform + draw logic in a more declarative way. Also linked to the reference - I was torn because as a whole the example is overly complex and we only need this portion - but still good to reference 👍

@paul121
Copy link
Member Author

paul121 commented Jul 18, 2024

Yes - thanks for the great feedback @symbioquine ! I renamed to "Snapshot" and have implemented the code changes you requested.

Still remaining is to simplify the SVG, I'll need to download the program and go through the steps but agree we should do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants